package mqtt

import (
	"strings"
	"time"

	"github.com/project-flogo/core/data/coerce"
)

type Settings struct {
	Broker       string `md:"broker,required"` // The broker URL
	Id           string `md:"id,required"`     // The id of client
	Username     string `md:"username"`        // The user's name
	Password     string `md:"password"`        // The user's password
	Store        string `md:"store"`           // The store for message persistence
	CleanSession bool   `md:"cleanSession"`    // Clean session flag
	// Topic        string                 `md:"topic,required"` // The topic to publish to
	Qos       int                    `md:"qos"`       // The Quality of Service
	SSLConfig map[string]interface{} `md:"sslConfig"` // SSL Configuration
}

type Input struct {
	Topic      string         `md:"topic"`
	Payload    interface{}    `md:"payload"` // The message to send
	Qos        int            `md:"qos"`
	IsRetained bool           `md:"isRetained"`
	Timeout    *time.Duration `md:"timeout"`
}

func (i *Input) ToMap() map[string]interface{} {
	return map[string]interface{}{
		"topic":      i.Topic,
		"payload":    i.Payload,
		"qos":        i.Qos,
		"isRetained": i.IsRetained,
		"timeout":    i.Timeout.String(),
	}
}

func (i *Input) FromMap(values map[string]interface{}) error {
	topic, err := coerce.ToString(values["topic"])
	if err != nil {
		return err
	}
	i.Topic = topic

	payload, err := coerce.ToBytes(values["payload"])
	if err != nil {
		return err
	}
	i.Payload = payload

	qos, err := coerce.ToInt(values["qos"])
	if err != nil {
		return err
	}
	i.Qos = qos

	isRetained, err := coerce.ToBool(values["isRetained"])
	if err != nil {
		return err
	}
	i.IsRetained = isRetained

	timeoutStr, err := coerce.ToString(values["timeout"])
	if err != nil {
		return err
	}
	if strings.TrimSpace(timeoutStr) == "" {
		i.Timeout = nil
	} else {
		d, err := time.ParseDuration(timeoutStr)
		if err != nil {
			return err
		}
		i.Timeout = &d
	}
	return nil
}

type Output struct {
	Err string `md:"err"` // The data recieved
}

func (o *Output) ToMap() map[string]interface{} {
	return map[string]interface{}{
		"err": o.Err,
	}
}

func (o *Output) FromMap(values map[string]interface{}) error {
	str, err := coerce.ToString(values["err"])
	if err != nil {
		return err
	}
	o.Err = str
	return nil
}
